package io.grpc.examples.helloworldtls;

import java.io.File;
import java.net.InetSocketAddress;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.logging.Logger;

import com.asgard.crypto.CryptoService;
import com.asgard.crypto.ECKey;
import com.asgard.keybox.KeyBox;

import io.grpc.Server;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.examples.helloworldtls.trust.MyTrustManagerFactory;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NettyServerBuilder;
import io.grpc.stub.StreamObserver;
import io.netty.handler.ssl.ClientAuth;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;

public class BCHelloWorldServerTls {
	private static final Logger logger = Logger.getLogger(BCHelloWorldServerTls.class.getName());

	private Server server;

	private String host;
	private int port;
	private String keyboxPath;

	public BCHelloWorldServerTls(String host, int port, String keyboxPath) {
		this.host = host;
		this.port = port;
		this.keyboxPath = keyboxPath;
	}

	private SslContextBuilder getSslContextBuilder() throws Exception {
		File keyBoxFile = new File(keyboxPath);
		KeyBox keyBox = new KeyBox();
		keyBox.loadFromFile(keyBoxFile, "PASSWORD");
		ECKey eckey = keyBox.getKey("ECKey");
		PrivateKey privateKey = eckey.getPrivateKey();
		X509Certificate x509Certificate = keyBox.getCertificate("ENROLL_CERT").getX509Cert();

		SslContextBuilder sslClientContextBuilder = SslContextBuilder.forServer(privateKey, x509Certificate)
				.clientAuth(ClientAuth.REQUIRE).trustManager(new MyTrustManagerFactory(""));

		return GrpcSslContexts.configure(sslClientContextBuilder, SslProvider.OPENSSL);
	}

	private void start() throws Exception {
		server = NettyServerBuilder.forAddress(new InetSocketAddress(host, port)).addService(new GreeterImpl())
				.sslContext(getSslContextBuilder().build()).build().start();
		logger.info("Server started, listening on " + port);
		Runtime.getRuntime().addShutdownHook(new Thread() {
			@Override
			public void run() {
				// Use stderr here since the logger may have been reset by its JVM shutdown
				// hook.
				System.err.println("*** shutting down gRPC server since JVM is shutting down");
				BCHelloWorldServerTls.this.stop();
				System.err.println("*** server shut down");
			}
		});
	}

	private void stop() {
		if (server != null) {
			server.shutdown();
		}
	}

	private void blockUntilShutdown() throws InterruptedException {
		if (server != null) {
			server.awaitTermination();
		}
	}

	public static void main(String[] args) throws Exception {
		CryptoService.setUseSM(false);
		String keyboxPath = BCHelloWorldServerTls.class.getClass().getResource("NotSM/resources/pbftvp01/keybox.xml")
				.getPath();
//        CryptoService.setUseSM(true);
//        String keyboxPath = "E:\\develop\\tomcat\\apache-tomcat-8.5.54-8203\\resources\\SMTrueSSL\\keybox.xml";

		final BCHelloWorldServerTls server = new BCHelloWorldServerTls("localhost", 7443, keyboxPath);
		server.start();
		server.blockUntilShutdown();
	}

	static class GreeterImpl extends GreeterGrpc.GreeterImplBase {

		@Override
		public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
			System.out.println("发送消息");
			HelloReply reply = HelloReply.newBuilder().setMessage("hi! Hello " + req.getName()).build();
			responseObserver.onNext(reply);
			responseObserver.onCompleted();
		}
	}
}